import sys,threading
import tkMessageBox
import tkSimpleDialog
from Tkinter import (
    Button,Label,StringVar,Entry,Tk,Menu
    )
ERROR = tkMessageBox.showerror

class GUI:

    def __init__ (self, parent, main_title, geo, stdpadx, stdpady):
        """ Sets class variables for main window """

        self.parent = parent
        self.menubar = Menu(self.parent)
        self.main_title = main_title
        self.geo = geo
        self.stdpadx = stdpadx
        self.stdpady = stdpady
        
        self.parent.title(main_title)
        self.parent.geometry(self.geo)

        self.calc = Calculator()

        self.dmg_dict = {}
        for effect in self.calc.effects.iterkeys():
            self.dmg_dict[effect] = StringVar()

    def build (self):
        """ Assembles Labels, Buttons, etc. then runs mainloop() """

        self._assembleMenu(self.menubar)
        self._assembleLabels(self.parent)
        self._assembleEntries(self.parent)
        self._assembleButtons(self.parent)

        self.parent.mainloop()


    def _assembleMenu (self, menubar):
        """ Assembles the dropdown menu bar for self.parent """

        filemenu = Menu(menubar, tearoff=0)
        filemenu.add_separator()
        filemenu.add_command(label="Quit %s" % self.main_title,
            command=lambda parent=self.parent: parent.quit())
        menubar.add_cascade(label="File", menu=filemenu)

        self.parent.config(menu=menubar)

    def _assembleEntries (self, parent):
        """ Draws 2 Entry() to enter level and condition damage """ 

        stdx = self.stdpadx
        stdy = self.stdpady
        
        self.level = StringVar()
        self.con_dmg = StringVar()

        self.entry_level = Entry(
            parent, textvariable=self.level, width=7)
        self.entry_level.grid(
            row=2, column=1, sticky="W", padx=stdx, pady=stdy)
        self.entry_con_dmg = Entry(
            parent, textvariable=self.con_dmg, width=7)
        self.entry_con_dmg.grid(
            row=3, column=1, sticky="W", padx=stdx)

    def _assembleLabels (self, parent):
        """ Draws 2 Label() for level and condition damage entries """

        stdx = self.stdpadx
        stdy = self.stdpady

        level_label_text  = "Character Level"  + " "*18
        condmg_label_text = "Condition Damage" + " "*17

        # Labels for Entries
        label_level = Label(parent, text=level_label_text)
        label_level.grid(
 
        row=2, column=0, sticky="W", padx=stdx, pady=stdy)

        label_con_dmg = Label(parent, text=condmg_label_text)
        label_con_dmg.grid(
            row=3, column=0, sticky="W", padx=stdx, pady=stdy)

        # Labels for damage values
        label_bleeding = Label(parent, text="Bleeding   (damage/sec)")
        label_bleeding.grid(
            row=5, column=0, sticky="W", padx=stdx, pady=stdy)

        label_confusion = Label(parent, text="Confusion (damage/skill use)")
        label_confusion.grid(
            row=6, column=0, sticky="W", padx=stdx, pady=stdy)

        label_poison = Label(parent, text="Poison      (damage/sec)")
        label_poison.grid(
            row=7, column=0, sticky="W", padx=stdx, pady=stdy)

        label_burning = Label(parent, text="Burning   (damage/sec)")
        label_burning.grid(
            row=8, column=0, sticky="W", padx=stdx, pady=stdy)

        # Labels holding damage values
        label_bleeding = Label(parent, textvariable=self.dmg_dict["Bleeding"])
        label_bleeding.grid(
            row=5, column=1, sticky="W", padx=stdx, pady=stdy)

        label_confusion = Label(parent, textvariable=self.dmg_dict["Confusion"])
        label_confusion.grid(
            row=6, column=1, sticky="W", padx=stdx, pady=stdy)

        label_poison = Label(parent, textvariable=self.dmg_dict["Poison"])
        label_poison.grid(
            row=7, column=1, sticky="W", padx=stdx, pady=stdy)

        label_burning = Label(parent, textvariable=self.dmg_dict["Burning"])
        label_burning.grid(
            row=8, column=1, sticky="W", padx=stdx, pady=stdy)

        for value in self.dmg_dict.values():
            value.set("0")

    def _assembleButtons (self, parent):
        """ Draws button that calls _displayResultsCall() """

        self.button_calc = Button(
            parent, text="Calculate", command=self._displayResultsCall)
        self.button_calc.grid(row=4, column=0, columnspan=2)


    def _displayResultsCall (self):
        """ Calls _displayResults() with args """

        self._displayResults (self.parent, self.level, self.con_dmg)

    def _displayResults (self, parent, level, con_dmg):
        """ "Prints" the user's character's DPS onto the main window """

        if not self._validate(): return

        lvl = int(level.get()) ; con_dmg = int(con_dmg.get())
        effects = self.calc.effects
        dmgdict = self.dmg_dict
        output = []

        x = 5
        for effect in effects.iterkeys():
            dmg = effects[effect](lvl, con_dmg)
            dmgdict[effect].set(dmg)
            x += 1

    def _validate (self):
        """ Validates all entries """

        if not self.level.get():
            ERROR("Whoops!",
                "You left the Level field blank!")
            return False
        if not self.level.get().isdigit():
            ERROR("Really?",
                "Isn't your character's level\n"
                "supposed to be a number?")
            return False

        if not self.con_dmg.get():
            ERROR("Whoops!",
                "You left the Condition Damage field blank!")
            return False
        if not self.con_dmg.get().isdigit():
            ERROR("Come on now...",
                "It's Condition DAMAGE. That's a number.")
            return False
        return True

class NewCharacter (tkSimpleDialog.Dialog):

    def __init__ (self, parent):

        tkSimpleDialog.Dialog.__init__(self, parent,  "New Character Profile")

        

class Calculator:

    def __init__ (self):

        self.effects = {
            "Burning":self.burning,
            "Bleeding":self.bleeding,
            "Poison":self.poison,
            "Confusion":self.confusion
            }

    def burning (self, level, condition_dmg):

        return str(int(8 + (4 * level) + (0.25 + condition_dmg)))

    def bleeding (self, level, condition_dmg):

        return str(int(0.5 * level + 0.05 * condition_dmg + 2.5))

    def poison (self, level, condition_dmg):

        return str(int(4 + level + (0.1 * condition_dmg)))

    def confusion (self, level, condition_dmg):

        return str(int(10 + (1.5 * level) + (0.15 * condition_dmg)))


if __name__ == "__main__":
    root = Tk()
    Main = GUI(
        root, "GW2 Damage Calculator", "275x205+400+400", stdpadx=5, stdpady=5)

    GUIthread = threading.Thread(None, Main.build(), None, ())
    GUIthread.start()
